//////////////////////////////////////////////////////////////////////////////////
//	 Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include <wx/wx.h>
#include <wx/listctrl.h>
#include <wx/spinctrl.h> 
#include <wx/clrpicker.h> 

#include <iostream>
#include <fstream>

#ifdef LINUX
#include <wx/imaglist.h>
#endif

#include "rcmdapp.h"
#include "mainwnd.h"
#include "logctrl.h"
#include "levelgraph.h"
#include "pingtab.h"
#include "utils.h"
#include "rtevents.h"

#define MAX_ENTRIES 5

enum cListColumns  { cListColumnHost=0, cListColumnStatus, cListColumnInt, cListColumnToActionCnt, cListColumnFailed, cListColumnAction, cListColumnLastPerformed };

enum cIDS
{
	ID_LIST=9701,
	IDC_ADD,
	IDC_EDT,
	IDC_RMV,
	IDC_BROWSEBUTTON,
	IDC_PATH_TO_FILE
};

static SEARCHFIELD sf[]=
{
	{ cSearchTypeString,	cListColumnHost,			_("Host")		},
	{ cSearchTypeString,	cListColumnStatus,			_("Status")		},
	{ cSearchTypeNumeric,	cListColumnInt,				_("Interval")	},
	{ cSearchTypeString,	cListColumnToActionCnt,		_("Threshold")	},
	{ cSearchTypeString,	cListColumnFailed,			_("Failures")	},
	{ cSearchTypeString,	cListColumnAction,			_("Action")		},
	{ cSearchTypeNumeric,	cListColumnLastPerformed,	_("Last Action Time")	},
};


BEGIN_EVENT_TABLE(CPingTab, wxPanel)
	EVT_BUTTON(IDC_ADD, CPingTab::OnAdd)
	EVT_BUTTON(IDC_EDT, CPingTab::OnEdit)
	EVT_BUTTON(IDC_RMV, CPingTab::OnRemove)

	EVT_UPDATE_UI(IDC_ADD, CPingTab::OnAddUI)
	EVT_UPDATE_UI(IDC_EDT, CPingTab::OnEditUI)
	EVT_UPDATE_UI(IDC_RMV, CPingTab::OnRemoveUI)

	EVT_ON_PING(wxID_ANY, CPingTab::OnProcessPingEvent)
END_EVENT_TABLE()

#define COLOR_ICON_W 8
#define COLOR_ICON_H 8


CPingTab::CPingTab(class wxWindow* pParent):wxPanel(pParent),
	m_tInt( 300 )
{
	int nFlags = wxALIGN_CENTER|wxALL|wxEXPAND;
	int nBorder(5);

	wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);

	//Ping graph
	wxStaticBoxSizer* pPingBox = new wxStaticBoxSizer( new
		wxStaticBox(this, wxID_ANY,  _("Round Trip Time")), wxHORIZONTAL);

	m_pLinePing = new CLevelGraph(this, CLevelGraph::cNormalGraphMode, CLevelGraph::cGraphLabelBottom, wxID_ANY);
	m_pLinePing->SetMinSize(wxSize(100,150));
	pPingBox->Add(m_pLinePing, 1, nFlags, 5);
	m_pLinePing->SetMesureName(wxT("ms"));
	m_pLinePing->SetTimePeriod( m_tInt );
	sizer->Add(pPingBox, 1, nFlags, nBorder);

	//Jitter
	wxStaticBoxSizer* pJitterBox = new wxStaticBoxSizer( new
		wxStaticBox(this, wxID_ANY,  _("Jitter")), wxHORIZONTAL);

	m_pLineJitter = new CLevelGraph(this, CLevelGraph::cNormalGraphMode, CLevelGraph::cGraphLabelBottom, wxID_ANY);
	m_pLineJitter->SetMinSize(wxSize(100,150));
	pJitterBox->Add(m_pLineJitter, 1, nFlags, 5);
	m_pLineJitter->SetMesureName(wxT("ms"));
	m_pLineJitter->SetTimePeriod( m_tInt );
	sizer->Add(pJitterBox, 1, nFlags, nBorder);

	ZONERANGE zone;
	ZONELIST list;

	//Bad
	zone.color = BAD_COLOR;
	zone.nFrom = 400;
	zone.nTo   = 100000;
	list.push_back(zone);

	//Fair
	zone.color = FAIR_COLOR;
	zone.nFrom = 200;
	zone.nTo   = 400;
	list.push_back(zone);

	//Good
	zone.color = GOOD_COLOR;
	zone.nFrom = 100;
	zone.nTo   = 200;
	list.push_back(zone);

	//Excelent
	zone.color = EXCELENT_COLOR;
	zone.nFrom = 0;
	zone.nTo   = 100;
	list.push_back(zone);

	m_pLinePing->SetZones(list);

	//Jitter
	{
		ZONERANGE zone;
		ZONELIST list;

		//Bad
		zone.color = BAD_COLOR;
		zone.nFrom = 60;
		zone.nTo   = 100000;
		list.push_back(zone);

		//Fair
		zone.color = FAIR_COLOR;
		zone.nFrom = 40;
		zone.nTo   = 60;
		list.push_back(zone);

		//Good
		zone.color = GOOD_COLOR;
		zone.nFrom = 20;
		zone.nTo   = 40;
		list.push_back(zone);

		//Excelent
		zone.color = EXCELENT_COLOR;
		zone.nFrom = 0;
		zone.nTo   = 20;
		list.push_back(zone);

		m_pLineJitter->SetZones(list);
	}

	//Ping Settings
	wxStaticBoxSizer* pListBox = new wxStaticBoxSizer( new
		wxStaticBox(this, wxID_ANY,  _("")), wxVERTICAL);

	//m_pList = new wxListCtrl(this, ID_LIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT);
	m_pList = new CLogCtrl<CPingTab>(this, ID_LIST);

	for (size_t i=0;i<sizeof(sf)/sizeof(sf[0]);i++)
	{
		m_pList->InsertColumn( sf[i].iFieldID, sf[i].strLabel );
	}

	m_pList->SetColumnWidth( cListColumnHost,			200	);
	m_pList->SetColumnWidth( cListColumnStatus,			80	);
	m_pList->SetColumnWidth( cListColumnInt,			80  );
	m_pList->SetColumnWidth( cListColumnToActionCnt,	80	);
	m_pList->SetColumnWidth( cListColumnFailed,			80	);
	m_pList->SetColumnWidth( cListColumnAction,			110	);
	m_pList->SetColumnWidth( cListColumnLastPerformed,	150	);

	pListBox->Add(m_pList, 1, nFlags, 10);

	wxBoxSizer* sizerButton = new wxBoxSizer(wxHORIZONTAL);

	m_pbtnAdd = new wxButton(this, IDC_ADD, _("Add"), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxBU_EXACTFIT);
	m_pbtnEdit = new wxButton(this, IDC_EDT, _("Edit"), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxBU_EXACTFIT);
	m_pbtnRemove= new wxButton(this, IDC_RMV, _("Remove"), wxDefaultPosition, wxDefaultSize, wxNO_BORDER|wxBU_EXACTFIT);

	sizerButton->Add(m_pbtnAdd, 0, nFlags|wxALIGN_LEFT, 5);
	sizerButton->Add(m_pbtnEdit, 0, nFlags|wxALIGN_CENTRE_HORIZONTAL, 5);
	sizerButton->Add(m_pbtnRemove, 0, nFlags|wxALIGN_RIGHT, 5);
	pListBox->Add(sizerButton, 0, nFlags, 0);

	sizer->Add(pListBox, 1, nFlags, nBorder);
	SetSizer(sizer);

	m_pImageList = new wxImageList(COLOR_ICON_W, COLOR_ICON_H);
	m_pList->SetImageList(m_pImageList, wxIMAGE_LIST_SMALL);
	m_pList->SetImageList(m_pImageList, wxIMAGE_LIST_STATE);

	LoadData();

	m_ping.SetObserver(this);
	m_ping.Start();
}

CPingTab::~CPingTab()
{
	m_ping.SetObserver(NULL);
	m_ping.Stop();
}

wxString CPingTab::GetLog()
{
	wxString strLog;

	if ( wxGetApp().GetMainWnd()->GetPropStorage().GetEnablePingLog() )
	{
		strLog+=_("Ping:");	
	}

	return strLog;
}

void CPingTab::SetTimeInterval(size_t tInt)
{
	m_tInt = tInt;

	m_pLinePing->SetTimePeriod( m_tInt );
	m_pLineJitter->SetTimePeriod( m_tInt );
}

void CPingTab::DispatchEntry(PingData& entry)
{
	m_pLinePing->SetData( entry.strHost, entry.result.stPingTime, entry.result.tEvent );
	m_pLineJitter->SetData( entry.strHost, entry.result.stPingJitter, entry.result.tEvent );

	if ( !entry.result.bPingResult )
	{
		//Total failures
		++entry.stPingFailedCnt;

		//Failures to action
		++entry.stPingFailuresToAction;
	}
	else
	{
		entry.stPingFailuresToAction = 0;
	}

	if ( entry.stPingFailuresToAction>=entry.stToActionCnt )
	{
		entry.stPingFailuresToAction = 0;

		switch( entry.action )
		{
			case cPingActionReboot:
			{
				entry.tLastFailed = entry.result.tEvent;

				wxString str = _("Router rebooted by Ping, host:");
				str+=entry.strHost;

				wxGetApp().GetMainWnd()->GetLogic().DoRouterReboot( str );
			}
			break;

			case cPingActionReconect:
			{
				entry.tLastFailed = entry.result.tEvent;

				LOGENTRY el;

				el.strCustomEvent = _("Ping Modem reconnect Action fired, host:");
				el.strCustomEvent +=entry.strHost;

				//Have to improve this
				wxString strCMD = wxT("<exec><exec_item id=\"start\" value=\"\">connection --up</exec_item></exec>");
					
				wxGetApp().GetMainWnd()->GetLogic().SendCMDToRouter( cCmdExecuteModemXML, strCMD, cCmdSubCodeADSLTweak, false );

				el.strCustomEvent+=_("Done!");
				wxGetApp().GetMainWnd()->GetLogic().AddToLog(el);

			}
			break;

			case cPingActionScript:
			{
				entry.tLastFailed = entry.result.tEvent;
				DoScriptEvent( entry );
			}
			break;

			case cPingActionRun:
			{
				entry.tLastFailed = entry.result.tEvent;

				LOGENTRY el;

				el.strCustomEvent = _("Ping Run Action fired,, host:");
				el.strCustomEvent+=entry.strHost;
				el.strCustomEvent+=wxT(". ");

				if ( entry.strPathToFile.empty() )
				{
					el.strCustomEvent+=_("Failed, empty file path");
				}
				else
				{
					wxExecute(  entry.strPathToFile, wxEXEC_ASYNC );
					el.strCustomEvent+=_("Done!");
				}

				wxGetApp().GetMainWnd()->GetLogic().AddToLog(el);
			}
			break;
		}
	}
}

void CPingTab::DoScriptEvent( const PingData& entry )
{
	LOGENTRY el;
	el.strCustomEvent = _("Ping Script Action fired, host:");
	el.strCustomEvent+=entry.strHost;

	el.strCustomEvent+=wxT(". ");

	if ( entry.strPathToFile.empty() )
	{
		el.strCustomEvent+=_("Failed, empty file path.");
	}
	else
	{
		wxString str;

		try
		{
			wxString strScriptFileName = entry.strPathToFile;

			std::string strIn;
			std::ifstream ifs ( strScriptFileName.ToAscii(), std::ifstream::in );

			while (ifs.good())
			{
				strIn+=ifs.get();
			}

			ifs.close();

			str = wxString::FromAscii( strIn.c_str() );

			if ( !str.empty() )
			{
				wxGetApp().GetMainWnd()->GetLogic().SendActionToRouter(str);

				el.strCustomEvent+=_("Done!");
			}
			else
			{
				el.strCustomEvent+=_("Failed, empty script file.");
			}
		}
		catch(...)
		{
			str+=_("Failed");
		}
	}

	wxGetApp().GetMainWnd()->GetLogic().AddToLog(el);
}

void CPingTab::OnProcessPingEvent(wxCommandEvent& event)
{
	int nItem = event.GetId();

	try
	{
		wxCriticalSectionLocker locker(m_csData);
		PingData& entry = m_list[nItem];

		if ( !entry.result.bDispatched )
		{
			entry.result.bDispatched= true;

			DispatchEntry(entry);

			m_pList->RefreshItem( nItem );
		}

	}
	catch(...)
	{
	}
}

void CPingTab::OnPingResult(int nItem, const PINGRESULT& result)
{
	try
	{
		wxCriticalSectionLocker locker(m_csData);
		PingData& entry = m_list[nItem];
		entry.result = result;

		wxCommandEvent eventCustom(wxEVT_PING);
		eventCustom.SetId(nItem);		
		wxPostEvent(this, eventCustom);
	}
	catch(...)
	{
	}
}

/////////////////////////////////////////////////////////////////
//UI Helppers
bool CPingTab::IsSelected()
{
	bool bRes(false);

	if ( m_pList )
	{
		long item = -1;
		item = m_pList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);

		bRes = item!=-1;
	}

	return bRes;
}

wxString CPingTab::GetItemText(long item, long column, wxWindowID id)
{
	wxString str;

	try
	{
		wxCriticalSectionLocker locker(m_csData);
		PingData& entry = m_list[item];
		str = FieldToString( column, entry, item);
	}
	catch(...)
	{
	}

	return str;
}

int	 CPingTab::GetItemImage(long item, wxWindowID id)
{
	return -1;
}

int CPingTab::GetItemColumnImage(long item, long column, wxWindowID id)
{
	int nImage(-1);

	if ( cListColumnHost == column )
	{
		nImage = item;
	}

	return nImage;
}

wxListItemAttr* CPingTab::GetItemAttr(long item, wxWindowID id)
{
	wxListItemAttr* pAttr(NULL);

	

	return pAttr;
}

wxString CPingTab::FieldToString( int column, PingData& entry, int iID)
{
	wxString str;
	
	try
	{
		switch(column)
		{
			case cListColumnHost:
				str = entry.strHost;
			break;

			case cListColumnStatus:
				str = GetStatusString( entry.cStatus );
			break;

			case cListColumnInt:
				str = wxString::Format(wxT("%u"), entry.stInterval);
			break;

			case cListColumnToActionCnt:
				str = wxString::Format(wxT("%u"), entry.stToActionCnt);
			break;

			case cListColumnFailed: 
				str = wxString::Format(wxT("%u"), entry.stPingFailedCnt);
			break;

			case cListColumnAction:
				str = GetActionString( entry.action );
			break;

			case cListColumnLastPerformed:
			{
				if ( -1!=entry.tLastFailed )
				{
					wxDateTime dt(entry.tLastFailed);
					str = dt.Format(_("%c"));
				}
			}
			break;
		}
	}
	catch (...)
	{
	}

	return str;
}

wxString CPingTab::GetStatusString(cPingStatus status)
{
	wxString str(_("None"));

	switch( status )
	{
		case cPingActive:
			str = _("Active");
		break;

		case cPingDisabled:
			str = _("Disabled");
		break;
	}

	return str;
}

wxString CPingTab::GetActionString(cPingFailedAction status)
{
	wxString str(_("None"));

	switch( status )
	{
		case cPingActionNone:
			str = _("None");
		break;

		case cPingActionReboot:
			str = _("Reboot");
		break;

		case cPingActionReconect:
			str = _("Reconnect");
		break;

		case cPingActionScript:
			str = _("Script");
		break;

		case cPingActionRun:
			str = _("Run");
		break;
	}

	return str;
}

void CPingTab::UpdateImageItem( int item )
{
	wxColor color;

	try
	{
		wxCriticalSectionLocker locker(m_csData);
		PingData& entry = m_list[item];
		color = entry.color;
	}
	catch(...)
	{
	}

	unsigned short  bits[COLOR_ICON_H];
	for( int i=0; i<COLOR_ICON_H; i++ )
	{
		bits[i] = (!i || i==COLOR_ICON_H-1)?0xFF:0;
	}

	wxBitmap bmp(COLOR_ICON_W, COLOR_ICON_H);
	wxMemoryDC dc;

	wxBitmap bmpMask((const char *)bits, COLOR_ICON_W, COLOR_ICON_H,1);
	wxMask* pMask = new wxMask(bmpMask);
	bmp.SetMask(pMask);
	dc.SelectObject(bmp);

	dc.Clear();

	wxBrush br(color);
	dc.SetBrush(br);

	dc.SetBackground( br ); 
	
	dc.DrawRectangle(0, 1, COLOR_ICON_W, COLOR_ICON_H-1);

	dc.SelectObject(wxNullBitmap);

	//Add new
	if ( item>=m_pImageList->GetImageCount() )
	{
		m_pImageList->Add( bmp );
	}
	else
	{
		m_pImageList->Replace(item, bmp);
	}
}

void CPingTab::LoadData()
{
	wxCriticalSectionLocker locker(m_csData);

	m_list = wxGetApp().GetMainWnd()->GetPropStorage().LoadPingList();

	for(size_t i=0;i<m_list.size();i++)
	{
		UpdateImageItem(i);

		m_pLinePing->SetColor( m_list[i].strHost, m_list[i].color );
		m_pLineJitter->SetColor( m_list[i].strHost, m_list[i].color );
	}

	((CLogCtrl<CPingTab>*)m_pList)->DataChanged();

	m_ping.SetPingList(m_list);
}


/////////////////////////////////////////////////////////////////
//UI Callbacks
void	CPingTab::OnAdd(wxCommandEvent& ev)
{
	try
	{
		PingData data;

		CPingDataDlg dlg(_("Add new server to Ping"), this, data );

		if ( dlg.ShowModal() == wxID_OK )
		{
			wxCriticalSectionLocker locker(m_csData);
			m_list.push_back(data);
			UpdateImageItem( m_list.size()-1 );
			wxGetApp().GetMainWnd()->GetPropStorage().SavePingList(m_list);
			((CLogCtrl<CPingTab>*)m_pList)->DataChanged();

			m_ping.SetPingList(m_list);
		}
	}catch(...)
	{
		wxMessageBox(_("Add operation failed!"), _("Error"),
		                         wxICON_WARNING | wxOK, this);
	}
}

void CPingTab::OnEdit(wxCommandEvent& ev)
{
	try
	{
		long item = -1;
		item = m_pList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);

		if ( item!=-1 )
		{
			PingData data = m_list[item];
			CPingDataDlg dlg(_("Edit Ping settings"), this, data );

			if ( dlg.ShowModal() == wxID_OK )
			{
				{
					wxCriticalSectionLocker locker(m_csData);
					m_list[item] = data;
					wxGetApp().GetMainWnd()->GetPropStorage().SavePingList(m_list);
					UpdateImageItem( item );
				}

				m_pLinePing->SetColor( data.strHost, data.color );
				m_pLineJitter->SetColor( data.strHost, data.color );

				m_ping.SetPingList(m_list);
			}

			((CLogCtrl<CPingTab>*)m_pList)->DataChanged();
		}
	}catch(...)
	{
		wxMessageBox(_("Edit operation failed!"), _("Error"),
		                         wxICON_WARNING | wxOK, this);
	}
}

void CPingTab::OnRemove(wxCommandEvent& ev)
{
	try
	{
		long item = -1;
		item = m_pList->GetNextItem(item, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED);

		if ( item!=-1 )
		{
			wxCriticalSectionLocker locker(m_csData);

			PINGDATALIST::iterator i = m_list.begin();
			std::advance( i, item);
			m_list.erase(i);

			m_ping.SetPingList(m_list);

			m_pImageList->Remove(item);

			wxGetApp().GetMainWnd()->GetPropStorage().SavePingList(m_list);
			((CLogCtrl<CPingTab>*)m_pList)->DataChanged(true);
		}
	}catch(...)
	{
		wxMessageBox(_("Remove operation failed!"), _("Error"),
		                         wxICON_WARNING | wxOK, this);
	}
}

void	CPingTab::OnAddUI(wxUpdateUIEvent& ev)
{
	int nItems(1000);

	if ( m_pList )
	{
		nItems = m_pList->GetItemCount();
	}

	ev.Enable( nItems<=MAX_ENTRIES );

}

void	CPingTab::OnEditUI(wxUpdateUIEvent& ev)
{
	ev.Enable( IsSelected() );
}

void CPingTab::OnRemoveUI(wxUpdateUIEvent& ev)
{
	ev.Enable( IsSelected() );
}

////////////////////////////////////////////////////////////////
//CPingDataDlg

BEGIN_EVENT_TABLE(CPingDataDlg, wxDialog)
	EVT_BUTTON(wxID_OK, CPingDataDlg::OnOk)
	EVT_UPDATE_UI(wxID_OK, CPingDataDlg::OnOkUI)
	EVT_UPDATE_UI(IDC_PATH_TO_FILE, CPingDataDlg::OnFileUI)
	EVT_UPDATE_UI(IDC_BROWSEBUTTON, CPingDataDlg::OnFileUI)
	EVT_BUTTON(IDC_BROWSEBUTTON, CPingDataDlg::OnAskFilePath)
END_EVENT_TABLE()


CPingDataDlg::CPingDataDlg(const wxString& strTitle, class wxWindow* pParent, PingData& data):
wxDialog(pParent, wxID_ANY, strTitle, wxDefaultPosition, wxDefaultSize, wxCAPTION|wxRESIZE_BORDER|wxCLOSE_BOX|wxSTAY_ON_TOP),
m_data(data)
{
	wxBoxSizer *sizer = new wxBoxSizer(wxVERTICAL);
	wxFlexGridSizer* pG = new wxFlexGridSizer(7, 2, 10, 5);

	wxStaticText* pST;

	//Host
	pST = new wxStaticText(this, -1, _("Host to ping:"));
	m_pHost = new wxTextCtrl(this, -1, data.strHost );
	pG->Add(pST);
	pG->Add(m_pHost, 1, wxEXPAND);


	//Interval
	pST = new wxStaticText(this, -1, _("Ping interval (sec):"));
	m_pInterval = new wxSpinCtrl(this, -1, wxString::Format(wxT("%u"), data.stInterval) );
	m_pInterval->SetRange(1, 60*60*24*7 );

	pG->Add(pST);
	pG->Add(m_pInterval, 1, wxEXPAND);

	//ActionCnt
	pST = new wxStaticText(this, -1, _("Number of failed pings to execute action:"));
	m_pActionCnt = new wxSpinCtrl(this, -1, wxString::Format(wxT("%u"), data.stToActionCnt) );
	m_pActionCnt->SetRange(0, 1000 );

	pG->Add(pST);
	pG->Add(m_pActionCnt, 1, wxEXPAND);

	//Action
	pST = new wxStaticText(this, -1, _("Action to perform:"));
	m_pAction = new wxComboBox(this, -1, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN|wxCB_READONLY );
	pG->Add(pST);
	pG->Add(m_pAction, 1, wxEXPAND);

	for(size_t i=cPingActionNone;i<=cPingActionRun;i++)
	{
		wxString item = CPingTab::GetActionString( (cPingFailedAction)i );
		m_pAction->Append(item, (void*)i);

		if (i==data.action)
		{
			m_pAction->SetSelection( i );
		}
	}

	int nFlagsSave  = wxRIGHT|wxALIGN_CENTRE_VERTICAL;
	int nBorder		= 5;

	//strPathToFile;
	pST = new wxStaticText(this, wxID_ANY, _("Path to file:"));
	m_pFileSizer = new wxBoxSizer(wxHORIZONTAL);
	{
		m_pFilePath = new wxTextCtrl(this, IDC_PATH_TO_FILE, data.strPathToFile, wxDefaultPosition, wxSize(100, wxDefaultSize.GetY()));
		m_pFileSizer->Add(m_pFilePath, 0, nFlagsSave, nBorder);

		wxButton* pBtn = new wxButton(this, IDC_BROWSEBUTTON, _T("..."), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT|wxNO_BORDER );
		m_pFileSizer->Add(pBtn, 0, nFlagsSave, nBorder);
	}
	
	pG->Add(pST);
	pG->Add(m_pFileSizer, 1, wxEXPAND);

	//color
	pST = new wxStaticText(this, -1, _("Color:"));
	m_pColor = new wxColourPickerCtrl (this, -1, data.color );
	pG->Add(pST);
	pG->Add(m_pColor, 0, wxALIGN_RIGHT);


	//Status
	pST = new wxStaticText(this, -1, _("Status:"));
	m_pStatus = new wxComboBox(this, -1, wxT(""), wxDefaultPosition, wxDefaultSize, 0, NULL, wxCB_DROPDOWN|wxCB_READONLY );
	pG->Add(pST);
	pG->Add(m_pStatus, 1, wxEXPAND);

	for(size_t i=cPingActive;i<=cPingDisabled;i++)
	{
		wxString item = CPingTab::GetStatusString( (cPingStatus)i );
		m_pStatus->Append(item, (void*)i);

		if (i==data.cStatus)
		{
			m_pStatus->SetSelection( i );
		}
	}

	pG->AddGrowableCol(1, 1);
	sizer->Add(pG, 1, wxALL|wxALIGN_CENTER, 10);

	wxSizer* sz = CreateStdDialogButtonSizer(wxOK|wxCANCEL);
	sizer->Add(sz, 0, wxALL|wxALIGN_CENTER, 10);
	
	SetSizer(sizer);

	Fit();
}

void CPingDataDlg::OnOk(wxCommandEvent& ev)
{
	//strHost
	if ( m_pHost )
	{
		m_data.strHost = m_pHost->GetValue();
	}

	//stInterval
	if ( m_pInterval )
	{
		m_data.stInterval = m_pInterval->GetValue();
	}

	//stToActionCnt
	if ( m_pActionCnt )
	{
		m_data.stToActionCnt = m_pActionCnt->GetValue();
	}

	//action
	if ( m_pAction )
	{
		cPingFailedAction action = (cPingFailedAction)GetSelectedItemDataInt(*m_pAction);
		m_data.action = action;
	}

	//strPathToFile
	if ( m_pFilePath )
	{
		m_data.strPathToFile = m_pFilePath->GetValue();
	}

	//color
	if ( m_pColor )
	{
		m_data.color = m_pColor->GetColour();
	}

	//cStatus
	if ( m_pStatus )
	{
		cPingStatus status = (cPingStatus)GetSelectedItemDataInt(*m_pStatus);
		m_data.cStatus = status;
	}

	EndModal(wxID_OK); 
}

void CPingDataDlg::OnOkUI(wxUpdateUIEvent& ev)
{
	bool bEnable(true);

	//Host
	if ( m_pHost && m_pHost->GetValue().empty() )
	{
		bEnable = false;
	}

	if ( m_pInterval && m_pInterval->GetValue()<=0 )
	{
		bEnable = false;
	}

	if ( m_pActionCnt && m_pActionCnt->GetValue()<0 )
	{
		bEnable = false;
	}

	cPingFailedAction action = (cPingFailedAction)GetSelectedItemDataInt(*m_pAction);

	if ( action==cPingActionScript || action==cPingActionRun )
	{
		if ( m_pFilePath && m_pFilePath->GetValue().empty() )
		{
			bEnable = false;
		}
	}

	ev.Enable(bEnable);
}

void CPingDataDlg::OnFileUI(wxUpdateUIEvent& ev)
{
	bool bEnable(false);

	cPingFailedAction action = (cPingFailedAction)GetSelectedItemDataInt(*m_pAction);

	if ( action==cPingActionScript || action==cPingActionRun )
	{
		bEnable = true;
	}

	ev.Enable(bEnable);
}

void CPingDataDlg::OnAskFilePath(wxCommandEvent& ev)
{
	try
	{
		wxFileDialog dlg(this, _("Choose a file"),
				wxT(""), wxT(""), wxT("*.*"), wxFD_OPEN|wxFD_FILE_MUST_EXIST );

		if ( wxID_OK ==dlg.ShowModal() )
		{
			m_pFilePath->SetValue(dlg.GetPath());
		}
	}
	catch(...)
	{
		wxMessageBox(_("Failed!"), _("Error"), wxICON_WARNING | wxOK, this);
	}
}

